﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics.Contracts;

namespace TemplateEngine
{
    internal class PeekReader
    {
        char[] _data;
        int index = 0;

        public PeekReader(TextReader tr)
        {
            Contract.Requires(tr != null);
            Contract.Ensures(_data != null);
            _data = tr.ReadToEnd().ToCharArray();
        }
        public PeekReader(char[] data)
        {
            Contract.Requires(data != null);
            Contract.Ensures(_data != null);
            _data = data;
        }
        public bool EOF
        {
            get { return index >= _data.Length; }
        }
        public int Available
        {
            get { return _data.Length - index; }
        }
        public bool PeekMatch(char[] test)
        {
            if (test == null)
            { return false; }
            int maxLength = Math.Min(test.Length, Available);
            for (int i = 0; i < maxLength; i++)
            {
                if (_data[index + i] != test[i])
                { return false; }
            }
            return maxLength > 0;
        }
        public int Read(char[] dest, int length)
        {
            if (dest == null) { return 0; }
            int maxLength = Math.Max(0, Math.Min(Math.Min(dest.Length, length), Available));
            for (int i = 0; i < maxLength; i++)
            {
                dest[i] = _data[i + index];
                System.Console.Out.Write(dest[i]);
            }
            index += maxLength;
            return maxLength;
        }
        public char ReadChar()
        {
            if (index >= _data.Length)
            { return char.MinValue; }
            char result = _data[index];
            index++;
            return result;
        }
        public char[] ReadChars(int length)
        {
            Contract.Requires(length >= 0);
            char[] result = new char[length];
            Read(result, length);
            return result;
        }
        public void Skip(char[] pattern)
        {
            if (pattern != null)
            { index = Math.Min(_data.Length, index + pattern.Length); }
        }
     
        [ContractInvariantMethod]
        private void AlwaysTrue()
        {
            Contract.Invariant(_data != null);
            Contract.Invariant(index >= 0);
            Contract.Invariant(index <= _data.Length);
        }
    }
}
